import type { ProColumns } from "@ant-design/pro-components";
import { ProTable } from "@ant-design/pro-components";
import API from "./services";
import { TYPE } from "../types";
import { useState, useRef } from "react";
import {
  Button, Form, Drawer, Space, Input, Select, Row, Col, Switch, Descriptions,
  message,
} from "antd";
import { CheckOutlined, LockOutlined, PlusOutlined } from "@ant-design/icons";
import OperationBar from "../../components/OperationBar";
import type { DescriptionsItemType } from "antd/es/descriptions";
import type { DefaultOptionType } from "antd/es/select";
import { md516 } from "../../utils/md5.js";
import { useAccess, Access } from "@umijs/max";

const required = true;
const titleMap = { Add: "新增", Edit: "编辑" };
const keys = "userName,password,name,phone,email,roleId,status,id,addTime," +
  "remark";
const labels = "用户名,登录密码,用户姓名,手机号码,电子邮箱,用户角色,用户状态,用户ID," +
  "注册日期,备注";
const roleMap: Record<number, string> = {}; // 根据角色id，获取角色名称。
type User = {
  userName0?: string;
  name0?: string;
  phone0?: string;
  status0?: boolean;
} & TYPE.User;

export default () => {
  const [visible, visibleSet] = useState(false);
  const [saveLoading, saveLoadingSet] = useState(false);
  const [action, actionSet] = useState<"Add" | "Edit">("Add");
  const [editId, editIdSet] = useState(0);
  const [display, displaySet] = useState<"form" | "desc">("form");
  const [descItems, descItemSet] = useState<DescriptionsItemType[]>([]);
  const [roleSelectData, roleSelectDataSet] = useState<DefaultOptionType[]>([]);
  const [roleSelectLoading, roleSelectLoadingSet] = useState(false);
  const [formValues, formValueSet] = useState<any>({});

  const [formRef] = Form.useForm();
  const tableRef = useRef<any>({});
  const ac = useAccess();

  const columns: ProColumns[] = [
    { title: "用户ID", dataIndex: "id", valueType: "digit", width: 60 },
    {
      title: "用户名",
      dataIndex: "userName",
      renderText: (text, record: TYPE.User) => (
        <OperationBar
          text={text}
          display="hover"
          textOnClick={() => {
            updateItems(record);
            openDrawer("desc");
          }}
          editOnClick={() => {
            const { id, userName, name, phone, status } = record;
            formRef.setFieldsValue({
              ...record,
              // 以下四个表单项控制台警告：[DOM] Found 2 elements with non-unique id
              // 目前尚未找到原因，暂且绕过这个问题。
              userName0: userName,
              name0: name,
              phone0: phone,
              status0: status,
            });
            actionSet("Edit");
            editIdSet(id);
            openDrawer("form");
          }}
          deleteOnClick={() => remove(record.id)}
        />
      ),
    },
    {
      title: "用户角色",
      dataIndex: "roleId",
      valueEnum: roleMap,
      renderText: text => roleMap[text],
    },
    { title: "用户姓名", dataIndex: "name" },
    { title: "手机号码", dataIndex: "phone", hideInSearch: true, width: 120 },
    { title: "电子邮箱", dataIndex: "email", hideInSearch: true },
    {
      title: "用户状态",
      dataIndex: "status",
      valueEnum: { true: "正常", false: "禁用" },
      renderText: text => text ?
        <CheckOutlined style={{ color: "#52c41a" }} /> :
        <LockOutlined style={{ color: "#f5222d" }} />,
      width: 80,
    },
    {
      title: "注册日期",
      dataIndex: "addTime",
      renderText: text => text.substr(0, 10),
      hideInSearch: true,
      width: 110,
    },
  ];

  const save = () => {
    formRef.validateFields().then(() => {
      const formData: User = { ...formValues };
      if (action === "Edit") {
        if (JSON.stringify(formData) === "{}") {
          message.info("你未做任何更改");
          return;
        }

        formData.id = editId;
      }
      const { userName0, name0, phone0, status0, password } = formData;
      if (userName0) formData.userName = userName0;
      if (name0) formData.name = name0;
      if (phone0) formData.phone = phone0;
      if (status0 !== undefined) formData.status = status0;
      delete formData.userName0;
      delete formData.name0;
      delete formData.phone0;
      delete formData.status0;
      if (password && password.length <= 15) formData.password = md516(password);
      saveLoadingSet(true);
      const func = action === "Add" ? API.userAdd : API.userEdit;
      func(formData).then(() => {
        saveLoadingSet(false);
        visibleSet(false);
        tableRef.current.reload();
      }).catch(() => saveLoadingSet(false));
    });
  };

  const remove = (id: number) => {
    API.userRemove(id).then(() => tableRef.current.reload());
  };

  const updateItems = (record: any) => {
    const { id } = record;
    const keyData = keys.split(",");
    const items: DescriptionsItemType[] = labels.split(",").map((label, index) => ({
      key: keyData[index], label, children: "",
    }));
    for (const key in record) {
      let value = record[key];
      // 渲染值
      switch (key) {
        case "status":
          value = value ? "正常" : "禁用";
          break;

        case "addTime":
          value = value.substr(0, 10);
          break;

        case "remark":
          if (!value) value = "无";
          break;

        case "roleId":
          value = roleMap[value];
          break;
      }
      const index = keyData.indexOf(key);
      if (items[index]) items[index].children = value;
    }
    descItemSet(items);
    editIdSet(id);
  };

  const openDrawer = (displayMode: "form" | "desc") => {
    displaySet(displayMode);
    visibleSet(true);
    if (displayMode === "form") formValueSet({});
  };

  const getRoleSelectData = () => {
    if (roleSelectData.length) return; // 有数据了就不用再请求

    roleSelectLoadingSet(true);
    API.roleSelectData().then((res: TYPE.Response) => {
      roleSelectLoadingSet(false);
      const data: TYPE.RoleItem[] = res.data;
      const renderData: DefaultOptionType[] = data.map(({ id, name }) => {
        roleMap[id] = name; // 设置映射关系
        return { value: id, label: name };
      });
      roleSelectDataSet(renderData);
    }).catch(() => roleSelectLoadingSet(false));
  };

  const title = (display === "desc" ? "查看" : titleMap[action]) + "用户信息";

  const form = (
    <Form
      form={formRef}
      labelCol={{ flex: "80px" }}
      onValuesChange={changedValues =>
        formValueSet({ ...formValues, ...changedValues })
      }
    >
      <Row gutter={{ md: 24, sm: 8 }}>
        <Col md={12} sm={24}>
          <Form.Item name="userName0" label="用户名" rules={[{ required }]}>
            <Input maxLength={20} autoComplete="nope" />
          </Form.Item>
        </Col>
        <Col md={12} sm={24}>
          <Form.Item name="password" label="登录密码" rules={[{ required }]}>
            <Input maxLength={15} autoComplete="new-password" />
          </Form.Item>
        </Col>

        <Col md={12} sm={24}>
          <Form.Item name="name0" label="用户姓名" rules={[{ required }]}>
            <Input maxLength={10} />
          </Form.Item>
        </Col>
        <Col md={12} sm={24}>
          <Form.Item name="phone0" label="手机号码" rules={[{ required }]}>
            <Input type="number" min={13000000000} max={19999999999} />
          </Form.Item>
        </Col>

        <Col md={12} sm={24}>
          <Form.Item name="email" label="电子邮箱" rules={[{ required }]}>
            <Input maxLength={50} />
          </Form.Item>
        </Col>
        <Col md={12} sm={24}>
          <Form.Item name="roleId" label="用户角色" rules={[{ required }]}>
            <Select allowClear loading={roleSelectLoading} options={roleSelectData} />
          </Form.Item>
        </Col>

        <Col md={12} sm={24}>
          <Form.Item
            name="status0"
            label="用户状态"
            initialValue={true}
            valuePropName="checked"
          >
            <Switch
              defaultChecked
              checkedChildren="正常"
              unCheckedChildren="禁用"
              disabled={action === "Add"} // 新增时固定启用
            />
          </Form.Item>
        </Col>

        <Col span={24}>
          <Form.Item name="remark" label="备注" initialValue="">
            <Input.TextArea
              showCount={true}
              maxLength={255}
              autoSize={{ minRows: 5, maxRows: 10 }}
            />
          </Form.Item>
        </Col>
      </Row>
    </Form>
  );

  const desc = <Descriptions bordered column={2} items={descItems} />;

  const contentMap = { form, desc };

  return (
    <>
      <ProTable
        headerTitle={(
          <Access accessible={ac.canUse("add")} fallback="用户管理">
            <Button
              type="primary"
              icon={<PlusOutlined />}
              onClick={() => {
                formRef.resetFields();
                actionSet("Add");
                editIdSet(0);
                openDrawer("form");
              }}
            >
              新增用户
            </Button>
          </Access>
        )}
        rowKey="id"
        columns={columns}
        request={API.user}
        pagination={false}
        actionRef={tableRef}
        onLoad={getRoleSelectData}
        footer={data => "总共 " + data.length + " 条"}
      />
      <Drawer
        title={title}
        width={768}
        open={visible}
        onClose={() => visibleSet(false)}
        styles={{ body: { paddingBottom: 0 }, footer: { textAlign: "right" } }}
        footer={display === "form" ? (
          <Space>
            <Button type="primary" loading={saveLoading} onClick={save}>
              保存
            </Button>
            <Button onClick={() => visibleSet(false)}>取消</Button>
          </Space>
        ) : null}
      >
        {contentMap[display]}
      </Drawer>
    </>
  );
};
